﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using UnityEditor;
using UnityEngine;

namespace DashFire.Assetbundle
{
  internal class ExportRes_SoloRes
  {
    static string[] s_ResExcludePattern = new string[] { ".cs", ".js", ".dll", ".a" };

    static HashSet<string> s_AssetsListContent = new HashSet<string>();

    internal static bool ExportClientResources()
    {
      return true;
    }
    internal static bool ExportDiffResources()
    {
      Dictionary<string, ExportResInfo> tExportResDict = ExportConfig.s_ExportResDict;
      List<string> tDiffAssetList = new List<string>();

      // 1.Init Environment
      if (!InitEnvironment()) {
        ExportConfig.Log("ExportDiffResources.InitEnvironment failed:");
        return false;
      }

      // 2.Generate solo res dependency tree
      SearchAssets("scene");
      SearchAssets("scene_fx");
      SearchAssets("hero");
      SearchAssets("hero_fx");
      SearchAssets("monster");
      SearchAssets("monster_fx");
      SearchAssets("npc");
      SearchAssets("goodsphoto");

      // 3.Collect solo res guid to s_SheetListContent
      string tmpGuid = string.Empty;
      foreach (string assetFile in ExportConfig.s_DiffContent) {
        string assetFileLower = assetFile.ToLower();
        if (!string.IsNullOrEmpty(assetFileLower)
          && !ExportConfig.IsEndWith(assetFile, s_ResExcludePattern)
          ) {
          if (File.Exists(assetFileLower)) {
            tmpGuid = AssetDatabase.AssetPathToGUID(assetFileLower);
            if (!string.IsNullOrEmpty(tmpGuid)) {
              tDiffAssetList.Add(tmpGuid);
              //ExportConfig.Log("CheckDiffFile Diff Asset:{0} Guid:{1}", assetFileLower, tmpGuid);
            }
          }
        }
      }

      // 4.Check ExportResInfo "m_IsNeedBuild" variable
      foreach (ExportResInfo info in tExportResDict.Values) {
        //ExportConfig.Log("CheckDiffFile Info Asset:{0} Guid:{1}", info.m_AssetName, info.FormatDependGuid());
        foreach (string diffItem in tDiffAssetList) {
          if (info != null
            && info.m_DependGuid.Contains(diffItem)
            && !string.IsNullOrEmpty(diffItem.Trim())) {
            s_AssetsListContent.Add(info.m_AssetName);
            info.m_IsNeedBuild = true;
            ExportConfig.Log("CheckDiffFile NeedBuild:{0} DependGuid:{1}", info.m_AssetName, diffItem);
          }
        }
      }

      // 5.Export all res
      if (s_AssetsListContent != null && s_AssetsListContent.Count > 0) {
        if (!Export()) {
          ExportConfig.Log("ExportDiffResources.s_AssetsListContent failed:");
          return false;
        }
        // 6.Export Res List
        if (!ExportRes_ResList.Export(true)) {
          ExportConfig.Log("ExportDiffResources.ExportRes_ResList failed:");
          return false;
        }
      }

      ExportConfig.Log("ExportRes_SoloRes.ExportDiffResources Success");
      return true;
    }
    internal static bool ExportSelectedResources()
    {
      Dictionary<string, ExportResInfo> tExportResDict = ExportConfig.s_ExportResDict;

      // 1.Init Environment
      if (!InitEnvironment()) {
        ExportConfig.Log("ExportSelectedResources.InitEnvironment failed:");
        return false;
      }

      // 2.Search selected solo res
      if (Selection.objects != null && Selection.objects.Length > 0) {
        foreach (UnityEngine.Object obj in Selection.objects) {
          string selectedFile = AssetDatabase.GetAssetPath(obj);
          if (selectedFile != null && !string.IsNullOrEmpty(selectedFile.Trim())) {
            if (File.Exists(selectedFile)) {
              s_AssetsListContent.Add(selectedFile);
            }
          } else {
            continue;
          }
        }
      }

      // 3.Generate ExportResInfo
      if (s_AssetsListContent != null && s_AssetsListContent.Count > 0) {
        foreach (string curFileInfo in s_AssetsListContent) {
          string assetPath = ExportConfig.FormatResourceName(curFileInfo);
          if (string.IsNullOrEmpty(assetPath)) {
            continue;
          }
          string assetPathLower = assetPath.ToLower();
          if (tExportResDict.ContainsKey(assetPathLower)) {
            ExportConfig.Log("GenBuildConfig GenResBuildDataByFile exist:" + assetPath);
            continue;
          }
          ExportResInfo data = new ExportResInfo();
          data.m_Id = ExportConfig.GenNextResId();
          data.m_AssetName = assetPathLower;
          data.m_AssetShortName = ExportConfig.FormatAssetShortName(assetPath);
          data.m_PackageName = ExportConfig.FormatPackageName(data.m_AssetName);
          data.m_Size = 0;
          data.m_MD5 = string.Empty;
          data.m_IsNeedBuild = true;
          data.m_Guid = AssetDatabase.AssetPathToGUID(assetPath);
          data.m_DependGuid = ExportConfig.FormatDependencySet(assetPath);
          tExportResDict.Add(assetPathLower, data);
        }
      }

      // 3.Export all res
      if (s_AssetsListContent != null && s_AssetsListContent.Count > 0) {
        if (!Export()) {
          ExportConfig.Log("ExportSelectedResources.s_AssetsListContent failed:");
          return false;
        }

        // 4.Export Res List
        if (!ExportRes_ResList.Export(true)) {
          ExportConfig.Log("ExportSelectedResources.ExportRes_ResList failed:");
          return false;
        }
      }

      ExportConfig.Log("ExportRes_SoloRes.ExportSelectedResources Success");
      return true;
    }
    private static bool InitEnvironment()
    {
      ExportConfig.Log("--------------------------------------------------------------");
      ExportConfig.Log("ExportRes_SoloRes Start...");

      s_AssetsListContent.Clear();
      string outputPath = ExportConfig.GetPlatformPath();
      if (!System.IO.Directory.Exists(outputPath)) {
        System.IO.Directory.CreateDirectory(outputPath);
      }
      if (!System.IO.Directory.Exists(outputPath)) {
        ExportConfig.Log("InitEnvironment create output:" + outputPath);
        return false;
      }

      ExportConfig.s_ExportResDict.Clear();
      return true;
    }
    internal static bool SearchAssets(string resType)
    {
      Dictionary<string, ExportResInfo> tExportResDict = ExportConfig.s_ExportResDict;

      List<ExportTargetInfo> targetList = ExportConfig.SearchExportTargetInfo(resType);
      if (targetList != null && targetList.Count > 0) {
        foreach (ExportTargetInfo info in targetList) {
          DirectoryInfo tTargetDir = new DirectoryInfo(info.m_TargetDir);
          if (!tTargetDir.Exists) {
            ExportConfig.Log("ExportRes_SceneSearchTree dir not exist:" + info.m_TargetDir);
            continue;
          }

          string[] tResBuildPattern = info.m_TargetParrern.Split(ExportConfig.s_ConfigSplit, StringSplitOptions.RemoveEmptyEntries);
          if (tResBuildPattern == null || tResBuildPattern.Length == 0) {
            ExportConfig.Log("ExportRes_SceneSearchTree pattern error:" + info.m_TargetParrern);
            continue;
          }
          FileInfo[] tTargetFiles = tResBuildPattern
            .SelectMany(i => tTargetDir.GetFiles(i, SearchOption.AllDirectories))
            .Distinct().ToArray();

          if (tTargetFiles != null && tTargetFiles.Length > 0) {
            foreach (FileInfo curFileInfo in tTargetFiles) {
              string assetPath = ExportConfig.FormatResourceName(curFileInfo.FullName);
              if (string.IsNullOrEmpty(assetPath)) {
                continue;
              }
              string assetPathLower = assetPath.ToLower();
              if (tExportResDict.ContainsKey(assetPathLower)) {
                ExportConfig.Log("GenBuildConfig GenResBuildDataByFile exist:" + assetPath);
                continue;
              }
              ExportResInfo data = new ExportResInfo();
              data.m_Id = ExportConfig.GenNextResId();
              data.m_AssetName = assetPathLower;
              data.m_AssetShortName = ExportConfig.FormatAssetShortName(assetPath);
              data.m_PackageName = ExportConfig.FormatPackageName(data.m_AssetName);
              data.m_Size = 0;
              data.m_MD5 = string.Empty;
              data.m_IsNeedBuild = false;
              data.m_Guid = AssetDatabase.AssetPathToGUID(assetPath);
              data.m_DependGuid = ExportConfig.FormatDependencySet(assetPath);
              tExportResDict.Add(assetPathLower, data);
            }
          }
        }
      }
      return true;
    }
    private static bool Export()
    {
      Dictionary<string, ExportResInfo> tExportResDict = ExportConfig.s_ExportResDict;

      string pathName = string.Empty;
      foreach (string resPath in s_AssetsListContent) {
        ExportResInfo data = tExportResDict[resPath.ToLower()];
        if (data != null) {
          try {
            pathName = ExportConfig.GetTargetPath(data);
            string pDir = Path.GetDirectoryName(pathName);
            if (!Directory.Exists(pDir)) {
              Directory.CreateDirectory(pDir);
            }
            if (data.m_AssetName.EndsWith(".unity")) {
              string[] levels = { data.m_AssetName };
              BuildPipeline.BuildStreamedSceneAssetBundle(levels, pathName, ExportConfig.s_BuildOptionTarget, ExportConfig.s_BuildOptionScene);
              if (ExportConfig.s_BuildOptionZip) {
                ZipHelper.ZipFile(pathName, pathName);
              }
            } else {
              UnityEngine.Object targetAssets = AssetDatabase.LoadMainAssetAtPath(data.m_AssetName);
              UnityEngine.Object[] assets = { targetAssets };
              string[] assetNames = { data.m_AssetName };
              if (targetAssets != null) {
                BuildPipeline.BuildAssetBundleExplicitAssetNames(
                  assets,
                  assetNames,
                  pathName,
                  ExportConfig.s_BuildOptionRes,
                  ExportConfig.s_BuildOptionTarget);
                if (ExportConfig.s_BuildOptionZip) {
                  ZipHelper.ZipFile(pathName, pathName);
                }
              }
            }
          } catch (System.Exception ex) {
            ExportConfig.Log("Export ExportResInfo failed ex:" + ex);
          }
        } else {
          ExportConfig.Log("Export ExportResInfo not exist:" + resPath);
        }
      }

      ExportConfig.Log("ExportRes_SoloRes.Exporte Success");
      return true;
    }
    #region Menu Item
    [MenuItem("Export/Export Selected/2.Solo Res/Export Client SoloRes", false, 41)]
    internal static void ExportClientSoloRes()
    {
      EditorUtility.DisplayDialog(
        "Confirm",
        "ExportClientResources SoloRes NO Need Export!",
        "OK");
    }
    [MenuItem("Export/Export Selected/2.Solo Res/Export Selected SoloRes", false, 42)]
    internal static void ExportSelectedSoloRes()
    {
      if (ExportConfig.Load()
        && ExportSelectedResources()) {
        EditorUtility.DisplayDialog(
          "Confirm",
          "ExportSelectedSoloRes Success!",
          "OK");
      } else {
        EditorUtility.DisplayDialog(
          "Confirm",
          "ExportSelectedSoloRes Failed!",
          "OK");
      }
    }
    [MenuItem("Assets/Export Selected/2.Solo Res/Export Client SoloRes", false, 41)]
    internal static void Assets_ExportClientSoloRes()
    {
      ExportClientSoloRes();
    }
    [MenuItem("Assets/Export Selected/2.Solo Res/Export Selected SoloRes", false, 42)]
    internal static void Assets_ExportSelectedSoloRes()
    {
      ExportSelectedSoloRes();
    }
    #endregion
  }
}
